﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class Timer : BaseManager {
    const string PARAM_delayTime = "delayTime";
    const string PARAM_repeatTimes = "repeatTimes";
    const string PARAM_callBack = "callBack";
    const string PARAM_startTime = "startTime";
    const string PARAM_executeTime = "executeTime";
    
    /// <summary>
    /// key:对象  value:update call back
    /// </summary>
	Dictionary<object, Action> toUpdate;
	Dictionary<object, Action> toLateUpdate;
	Dictionary<object, Action> toFixedUpdate;

//    Dictionary<string, Action> toUpdate;
//    Dictionary<string, Action> toLateUpdate;
//    Dictionary<string, Action> toFixedUpdate;

    /// <summary>
    /// key:id ;value-key:param name ;value-value: param value
    /// </summary>
    Dictionary<int, Dictionary<string, object>> timers;

    /// <summary>
    /// 用于定时器识别的id
    /// </summary>
    int timerId = 0;
    void Start() {
		toUpdate = new Dictionary<object, Action>();
		toLateUpdate = new Dictionary<object, Action>();
		toFixedUpdate = new Dictionary<object, Action>();
        timers = new Dictionary<int, Dictionary<string, object>>();
    }

    void Update()
    {
        //updatebeat
        if (toUpdate != null && toUpdate.Count > 0)
        {
            foreach (Action action in toUpdate.Values)
            {
                action();
            }
        }
        //timer
        if (timers != null && timers.Count > 0)
        {
            float tempTime = Time.realtimeSinceStartup;
            Dictionary<int, Dictionary<string, object>> bufferTimer = new Dictionary<int, Dictionary<string, object>>(timers);
            foreach (Dictionary<string, object> timer in bufferTimer.Values)
            {
                if ((int)timer[PARAM_repeatTimes] != 0 && (float)timer[PARAM_executeTime] <= tempTime)
                {
                    if (timer[PARAM_callBack] != null)
                    {
                        ((Action)timer[PARAM_callBack])();
                    }
                    timer[PARAM_repeatTimes] = (int)timer[PARAM_repeatTimes] - 1;
                    timer[PARAM_executeTime] = (float)timer[PARAM_executeTime] + (float)timer[PARAM_delayTime];
                }
            }
            //移除执行完的timer
            RemoveOverTimer();
        }
    }

    void LateUpdate() {
        if (toLateUpdate != null && toLateUpdate.Count > 0)
        {
            foreach (Action action in toLateUpdate.Values)
            {
                action();
            }
        }
    }

    void FixedUpdate() {
        if (toFixedUpdate != null && toFixedUpdate.Count > 0)
        {
            foreach (Action action in toFixedUpdate.Values)
            {
                action();
            }
        }
    }

    /// <summary>
    /// 相同类的update回调重复添加，会用新的替换旧的
    /// 注意传进来的作为key的obj，如果出了问题，可能会出现未执行updateCB的情况，产生未知错误
    /// </summary>
    /// <param name="className"></param>
    /// <param name="callBack"></param>
	public void UpdateBeat(object obj,Action callBack) {
		Debug.Log("UpdateBeat:" + obj.ToString());
		if (toUpdate.ContainsKey(obj))
		{
	    	Debug.Log("UpdateBeat 重复添加了（新的会替换旧的）:" + obj.ToString());
            toUpdate[obj] = callBack;
		}
		else {
			toUpdate.Add(obj, callBack);
		}
	}

	public void RemoveUpdateBeat(object obj) {
		Debug.Log("RemoveUpdateBeat:" + obj.ToString());
		if (toUpdate.ContainsKey(obj))
		{
			toUpdate.Remove(obj);
		}
	}

	public void RemoveAllUpdateBeat(){
		toUpdate.Clear ();
	}

    /// <summary>
    /// 相同类的latedupdate回调重复添加，会用新的替换旧的
    /// </summary>
    /// <param name="className"></param>
    /// <param name="callBack"></param>
	public void LateUpdateBeat(object obj, Action callBack)
    {
		if (toLateUpdate.ContainsKey(obj))
        {
	    	Debug.Log("LateUpdateBeat 重复添加了（新的会替换旧的）:" + obj.ToString());
            toLateUpdate[obj] = callBack;
        }
        else
        {
			toLateUpdate.Add(obj, callBack);
        }
    }

	public void RemoveLateUpdateBeat(object obj)
    {
		if (toLateUpdate.ContainsKey(obj))
        {
			toLateUpdate.Remove(obj);
        }
    }

	public void RemoveAllLateUpdateBeat(){
		toLateUpdate.Clear ();
	}

    /// <summary>
    /// 相同类的fixedupdate回调重复添加，会用新的替换旧的
    /// </summary>
    /// <param name="className"></param>
    /// <param name="callBack"></param>
	public void FixedUpdateBeat(object obj, Action callBack)
    {
		if (toFixedUpdate.ContainsKey(obj))
        {
	    	Debug.Log("FixedUpdateBeat 重复添加了（新的会替换旧的）:" + obj.ToString());
            toFixedUpdate[obj] = callBack;
        }
        else
        {
			toFixedUpdate.Add(obj, callBack);
        }
    }

	public void RemoveFixedUpdateBeat(object obj)
    {
		if (toFixedUpdate.ContainsKey(obj))
        {
			toFixedUpdate.Remove(obj);
        }
    }

	public void RemoveAllFixedUpdateBeat(){
		toFixedUpdate.Clear ();
	}

	public void ClearAllBeat(){
		RemoveAllUpdateBeat ();
		RemoveAllLateUpdateBeat ();
		RemoveAllFixedUpdateBeat ();
	}

    /// <summary>
    /// 添加一个定时器回调，每隔delayTime执行一次，总共执行repeatTimes次,为负数默认一直执行
    /// </summary>
    /// <param name="delayTime"></param>
    /// <param name="callBack"></param>
    /// <param name="repeatTimes"></param>
    public int AddTimer(float delayTime,Action callBack,int repeatTimes) {
        Dictionary<string, object> paramDic = new Dictionary<string, object>();
        paramDic.Add(PARAM_delayTime, delayTime);
        paramDic.Add(PARAM_repeatTimes, repeatTimes);
        paramDic.Add(PARAM_callBack, callBack);
        paramDic.Add(PARAM_startTime, Time.realtimeSinceStartup);
        paramDic.Add(PARAM_executeTime, Time.realtimeSinceStartup+delayTime);
        timers.Add(++timerId, paramDic);
		return timerId;
    }

    public void RemoveTimer(Action callBack) {
        Debug.Log("before REMOVE TIMER:" + timers.Count);
        foreach (int key in timers.Keys) {
            if (timers[key].ContainsValue(callBack)) {
                timers.Remove(key);
                break;
            }
        }
        Debug.Log("after REMOVE TIMER:" + timers.Count);
    }

	public void RemoveTimer(int timerId) {
		Debug.Log("before REMOVE TIMER:" + timers.Count);
		if (timerId>0&& timers.ContainsKey(timerId)) {
			timers.Remove(timerId);
		}
		Debug.Log("after REMOVE TIMER:" + timers.Count);
	}

    public void RemoveOverTimer() {
        //在迭代过程中，Dictionary 变量及Value是只读的，C#有保护机制，不允许在这个过程中修改这些变量。
        List<int> temp = new List<int>();
        foreach (int key in timers.Keys)
        {
            {
                if ((int)(timers[key][PARAM_repeatTimes]) == 0)//不用<=0是因为执行次数为负数默认为可以一直执行
                {
                    temp.Add(key);
                }
            }
        }
        foreach (int key in temp) {
            timers.Remove(key);
        }
    }

	public void ClearAllTimer(){
		timers.Clear ();
	}
}
